package com.ccteam.fluidmusic.ui.playlist

import android.app.Application
import android.os.Parcelable
import androidx.lifecycle.*
import com.ccteam.fluidmusic.utils.Event
import com.ccteam.fluidmusic.utils.UploadFileUtils
import com.ccteam.fluidmusic.view.bean.ErrorMessage
import com.ccteam.fluidmusic.view.bean.LoadMessage
import com.ccteam.model.Resource
import com.ccteam.network.ApiError
import com.ccteam.shared.domain.file.UploadImageTokenDataUseCase
import com.ccteam.shared.domain.playlistsheet.PlaylistSheetEditDataUseCase
import com.orhanobut.logger.Logger
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
import javax.inject.Inject

/**
 * @author Xiaoc
 * @since 2021/3/17
 *
 * 歌单编辑ViewModel层
 * 负责存储编辑歌单时的数据以及提交图片操作
 */
@HiltViewModel
class PlaylistSheetEditViewModel @Inject constructor(
    application: Application,
    private val uploadImageTokenDataUseCase: UploadImageTokenDataUseCase,
    private val uploadFileUtils: UploadFileUtils,
    private val playlistSheetEditDataUseCase: PlaylistSheetEditDataUseCase,
    savedStateHandle: SavedStateHandle
) : AndroidViewModel(application) {

    private val _uploadPhotoStatus = MutableLiveData<Event<LoadMessage>>()
    val uploadPhotoStatus: LiveData<Event<LoadMessage>> get() = _uploadPhotoStatus

    private val originPlaylistSheet: PlaylistSheetEditInfo? = savedStateHandle["playlistSheetInfo"]

    private val _editPlaylistSheet = MutableLiveData<PlaylistSheetEditInfo>(originPlaylistSheet)
    val editPlaylistSheet: LiveData<PlaylistSheetEditInfo> get() = _editPlaylistSheet

    private val _loadMessage = MutableLiveData<Event<LoadMessage>>()
    val loadMessage: LiveData<Event<LoadMessage>> get() = _loadMessage

    fun setPlaylistSheetImgUrl(imgUri: String) {
        uploadPhoto(imgUri)
    }

    fun setPlaylistSheetInfo(playlistName: String, playlistIntroduction: String) {
        _editPlaylistSheet.value?.playlistName = playlistName
        _editPlaylistSheet.value?.playlistIntroduction = playlistIntroduction
    }

    fun updatePlaylistSheetInfo() {
        _editPlaylistSheet.value = _editPlaylistSheet.value
    }

    fun editPlaylistSheetInfo(
        playlistName: String,
        playlistIntroduction: String
    ) {
        setPlaylistSheetInfo(playlistName, playlistIntroduction)
        _editPlaylistSheet.value?.let {
            if (it.playlistName.isEmpty()) {
                _loadMessage.value =
                    Event(LoadMessage.Error(ErrorMessage("歌单名不能为空", ApiError.serverErrorCode)))
                return@let
            }
            if (it.playlistName.length > 20) {
                _loadMessage.value = Event(
                    LoadMessage.Error(
                        ErrorMessage(
                            "歌单名长度太长，20字以内",
                            ApiError.serverErrorCode
                        )
                    )
                )
                return@let
            }
            _loadMessage.value = Event(LoadMessage.Loading)

            Logger.d("修改歌单内容：$it")
            viewModelScope.launch {
                // 修改歌单内容，仅修改名称和介绍两个字段
                val result = playlistSheetEditDataUseCase(
                    PlaylistSheetEditDataUseCase.EditPlaylistRequest(
                        id = it.id,
                        playlistName = it.playlistName,
                        playlistIntroduction = it.playlistIntroduction
                    )
                )

                if (result is Resource.Success) {
                    _loadMessage.value = Event(LoadMessage.Success)
                } else {
                    _loadMessage.value =
                        Event(LoadMessage.Error(ErrorMessage(result.message, result.errorCode)))
                }
            }
        }

    }

    private fun uploadPhoto(imgUri: String) {
        val application = getApplication<Application>()
        _uploadPhotoStatus.value = Event(LoadMessage.Loading)

        // 如果选择的图片和原来的图片不符且不是空的，则上传至七牛云
        if (imgUri.isNotEmpty()
            && imgUri != originPlaylistSheet?.playlistImgUrl
        ) {

            viewModelScope.launch {
                val result = uploadImageTokenDataUseCase(null)

                // 检测图片上传token是否获取成功
                if (result !is Resource.Success) {
                    _uploadPhotoStatus.postValue(
                        Event(
                            LoadMessage.Error(
                                ErrorMessage("上传图片失败 get Token fail!")
                            )
                        )
                    )
                    return@launch
                }

                val token = result.data

                uploadFileUtils.upload(application, token, imgUri,
                    {}, { fileUrl ->

                        updateHeaderUrl(fileUrl)
                    }, { errorMessage ->
                        _uploadPhotoStatus.postValue(
                            Event(
                                LoadMessage.Error(
                                    ErrorMessage(errorMessage)
                                )
                            )
                        )
                    })


            }
        }
    }

    /**
     * 更新头像字段内容
     */
    private fun updateHeaderUrl(headerUrl: String) {
        _editPlaylistSheet.value?.let {

            // 上传成功头像后获得头像路径，并更新对应头像字段
            viewModelScope.launch {
                val editResult = playlistSheetEditDataUseCase(
                    PlaylistSheetEditDataUseCase.EditPlaylistRequest(
                        id = it.id,
                        playlistImgUrl = headerUrl
                    )
                )

                if (editResult is Resource.Success) {
                    _editPlaylistSheet.value?.playlistImgUrl = headerUrl
                    _editPlaylistSheet.postValue(_editPlaylistSheet.value)
                    _uploadPhotoStatus.postValue(Event(LoadMessage.Success))
                } else {
                    _uploadPhotoStatus.postValue(
                        Event(
                            LoadMessage.Error(
                                ErrorMessage(editResult.message, editResult.errorCode)
                            )
                        )
                    )
                }
            }
        } ?: run {
            _uploadPhotoStatus.postValue(
                Event(
                    LoadMessage.Error(
                        ErrorMessage("未知错误", ApiError.unknownCode)
                    )
                )
            )
        }
    }

    override fun onCleared() {
        super.onCleared()

        uploadFileUtils.cancelUpload()
    }

}

@Parcelize
data class PlaylistSheetEditInfo(
    val id: String,
    var playlistName: String,
    var playlistImgUrl: String,
    var playlistIntroduction: String
) : Parcelable